package com.inforich.report.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.inforich.common.core.text.Convert;
import com.inforich.common.utils.DateUtils;
import com.inforich.report.IReportService;
import com.inforich.report.domain.ResourceBooking;
import com.inforich.report.domain.ResourceFilings;
import com.inforich.report.domain.ResourceLandInfo;
import com.inforich.report.domain.ResourceRubbishProduce;
import com.inforich.report.domain.ResourceRubbishTransport;
import com.inforich.report.domain.ResourceUnsign;
import com.inforich.report.domain.ResourceVehicleDetail;
import com.inforich.report.domain.ResourceVehicleMonth;
import com.inforich.report.domain.ResourceVehicleOut;
import com.inforich.report.domain.ResourceVehicleOutDetail;
import com.inforich.report.domain.ResourceVehicleOutTransport;
import com.inforich.report.mapper.ReportMapper;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @description: some desc
 * @author: HJM
 * @date: 2023/7/4
 */
@Service
public class ReportServiceImpl implements IReportService {

  @Autowired
  private ReportMapper reportMapper;

  @Override
  public Page<ResourceFilings> pageResourceFilings(Page<ResourceFilings> page,
      Map<String, Object> map) {
    return reportMapper.pageResourceFilings(page, map);
  }

  @Override
  public List<ResourceFilings> listResourceFilings(Map<String, Object> map) {
    return reportMapper.listResourceFilings(map);
  }

  @Override
  public Page<ResourceBooking> pageResourceBooking(Page<ResourceBooking> page,
      Map<String, Object> map) {
    reportMapper.pageResourceBooking(page, map);
    BigDecimal inorganicWeight = page.getRecords().stream()
        .filter(l -> l.getInorganicWeight() != null)
        .map(ResourceBooking::getInorganicWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
    BigDecimal metalWeight = page.getRecords().stream()
        .filter(l -> l.getMetalWeight() != null)
        .map(ResourceBooking::getMetalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
    BigDecimal woodWeight = page.getRecords().stream()
        .filter(l -> l.getWoodWeight() != null)
        .map(ResourceBooking::getWoodWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
    BigDecimal otherWeight = page.getRecords().stream()
        .filter(l -> l.getOtherWeight() != null)
        .map(ResourceBooking::getOtherWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
    BigDecimal disposalPlanWeight = page.getRecords().stream()
        .filter(l -> l.getDisposalPlanWeight() != null)
        .map(ResourceBooking::getDisposalPlanWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
    ResourceBooking booking = new ResourceBooking();
    booking.setProjectName("合计");
    booking.setInorganicWeight(inorganicWeight);
    booking.setMetalWeight(metalWeight);
    booking.setWoodWeight(woodWeight);
    booking.setOtherWeight(otherWeight);
    booking.setDisposalPlanWeight(disposalPlanWeight);
    if (CollUtil.isNotEmpty(page.getRecords())) {
      page.getRecords().add(booking);
    }
    return page;
  }

  @Override
  public List<ResourceBooking> listResourceBooking(Map<String, Object> map) {
    return reportMapper.listResourceBooking(map);
  }

  @Override
  public Page<ResourceRubbishProduce> pageResourceRubbishProduce(Page<ResourceRubbishProduce> page,
      Map<String, Object> map) {
    reportMapper.pageResourceRubbishProduce(page, map);
    page.getRecords().forEach(l -> {
      l.setInTotalWeight(Convert.toBigDecimal(l.getInTotalWeight(), BigDecimal.ZERO));
      l.setOutProjectTotalWeight(
          Convert.toBigDecimal(l.getOutProjectTotalWeight(), BigDecimal.ZERO));
    });
    BigDecimal buildingArea = page.getRecords().stream().filter(l -> l.getBuildingArea() != null)
        .map(ResourceRubbishProduce::getBuildingArea).reduce(BigDecimal.ZERO, BigDecimal::add);
    BigDecimal inTotalWeight = page.getRecords().stream().filter(l -> l.getBuildingArea() != null)
        .map(ResourceRubbishProduce::getInTotalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
    BigDecimal outProjectTotalWeight = page.getRecords().stream()
        .filter(l -> l.getBuildingArea() != null)
        .map(ResourceRubbishProduce::getOutProjectTotalWeight)
        .reduce(BigDecimal.ZERO, BigDecimal::add);
    ResourceRubbishProduce produce = new ResourceRubbishProduce();
    produce.setBuildingArea(buildingArea);
    produce.setInTotalWeight(inTotalWeight);
    produce.setOutProjectTotalWeight(outProjectTotalWeight);
    produce.setProjectName("合计");
    if (CollUtil.isNotEmpty(page.getRecords())) {
      page.getRecords().add(produce);
    }
    return page;
  }

  @Override
  public List<ResourceRubbishProduce> listResourceRubbishProduce(Map<String, Object> map) {
    List<ResourceRubbishProduce> list = reportMapper.listResourceRubbishProduce(map);
    list.forEach(l -> {
      l.setInTotalWeight(Convert.toBigDecimal(l.getInTotalWeight(), BigDecimal.ZERO));
      l.setOutProjectTotalWeight(
          Convert.toBigDecimal(l.getOutProjectTotalWeight(), BigDecimal.ZERO));
    });
    return list;
  }

  @Override
  public Page<ResourceRubbishTransport> pageResourceRubbishTransport(
      Page<ResourceRubbishTransport> page, Map<String, Object> map) {
    reportMapper.pageResourceRubbishTransport(page, map);
    page.getRecords().forEach(l -> {
      l.setOutState(l.getBeginTime() != null ? "是" : "否");
      l.setInState(l.getEndTime() != null ? "是" : "否");
    });
    return page;
  }

  @Override
  public List<ResourceRubbishTransport> listResourceRubbishTransport(Map<String, Object> map) {
    List<ResourceRubbishTransport> list = reportMapper.listResourceRubbishTransport(map);
    list.forEach(l -> {
      l.setOutState(l.getBeginTime() != null ? "是" : "否");
      l.setInState(l.getEndTime() != null ? "是" : "否");
    });
    return list;
  }

  @Override
  public Page<ResourceVehicleDetail> pageResourceVehicleDetail(Page<ResourceVehicleDetail> page,
      Map<String, Object> map) {
    return reportMapper.pageResourceVehicleDetail(page, map);
  }

  @Override
  public List<ResourceVehicleDetail> listResourceVehicleDetail(Map<String, Object> map) {
    return reportMapper.listResourceVehicleDetail(map);
  }

  @Override
  public Page<ResourceVehicleMonth> pageResourceVehicleMonth(Page<ResourceVehicleMonth> page,
      Map<String, Object> map) {
    reportMapper.pageResourceVehicleMonth(page, map);
    Map<String, BigDecimal> totalMap = listResourceVehicleTotalMap(map);
    page.getRecords().forEach(l -> {
      l.setMonthWeight(Convert.toBigDecimal(l.getMonthWeight(), BigDecimal.ZERO));
      l.setTotalWeight(Convert.toBigDecimal(totalMap.get(l.getProjectId()), BigDecimal.ZERO));
    });

    ResourceVehicleMonth month = new ResourceVehicleMonth();
    month.setDisposalLandName("合计");
    BigDecimal monthWeight = page.getRecords().stream().filter(l -> l.getMonthWeight() != null)
        .map(ResourceVehicleMonth::getMonthWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
    BigDecimal totalWeight = page.getRecords().stream().filter(l -> l.getTotalWeight() != null)
        .map(ResourceVehicleMonth::getTotalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
    month.setMonthWeight(monthWeight);
    month.setTotalWeight(totalWeight);
    if (CollUtil.isNotEmpty(page.getRecords())) {
      page.getRecords().add(month);
    }
    return page;
  }

  @Override
  public List<ResourceVehicleMonth> listResourceVehicleMonth(Map<String, Object> map) {
    List<ResourceVehicleMonth> list = reportMapper.listResourceVehicleMonth(map);
    Map<String, BigDecimal> totalMap = listResourceVehicleTotalMap(map);
    list.forEach(l -> {
      l.setMonthWeight(Convert.toBigDecimal(l.getMonthWeight(), BigDecimal.ZERO));
      l.setTotalWeight(Convert.toBigDecimal(totalMap.get(l.getProjectId()), BigDecimal.ZERO));
    });
    return list;
  }

  @Override
  public Page<ResourceLandInfo> pageResourceLandInfo(Page<ResourceLandInfo> page,
      Map<String, Object> map) {
    reportMapper.pageResourceLandInfo(page, map);
    Map<String, BigDecimal> totalMap = listResourceLandInfoTotalMap(map);
    page.getRecords().forEach(l -> {
      String key =
          l.getDisposalLandId() + "_" + l.getSysRubbishType() + "_" + l.getSysRubbishTypeSub();
      l.setTotalWeight(Convert.toBigDecimal(totalMap.get(key), BigDecimal.ZERO));
    });

    BigDecimal weight = page.getRecords().stream().filter(l -> l.getWeight() != null)
        .map(ResourceLandInfo::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
    BigDecimal totalWeight = page.getRecords().stream().filter(l -> l.getTotalWeight() != null)
        .map(ResourceLandInfo::getTotalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
    ResourceLandInfo info = new ResourceLandInfo();
    info.setDisposalLandName("合计");
    info.setWeight(weight);
    info.setTotalWeight(totalWeight);
    page.getRecords().add(info);
    return page;
  }

  @Override
  public List<ResourceLandInfo> listResourceLandInfo(Map<String, Object> map) {
    List<ResourceLandInfo> list = reportMapper.listResourceLandInfo(map);
    Map<String, BigDecimal> totalMap = listResourceLandInfoTotalMap(map);
    list.forEach(l -> {
      String key =
          l.getDisposalLandId() + "_" + l.getSysRubbishType() + "_" + l.getSysRubbishTypeSub();
      l.setTotalWeight(Convert.toBigDecimal(totalMap.get(key), BigDecimal.ZERO));
    });
    return list;
  }

  @Override
  public Page<ResourceVehicleOut> pageResourceVehicleOut(Page<ResourceVehicleOut> page,
      Map<String, Object> map) {
    reportMapper.pageResourceVehicleOut(page, map);
    BigDecimal netWeight = page.getRecords().stream().filter(l -> l.getNetWeight() != null)
        .map(ResourceVehicleOut::getNetWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
    ResourceVehicleOut out = new ResourceVehicleOut();
    out.setNetWeight(netWeight);
    out.setDisposalLandName("合计");
    if (CollUtil.isNotEmpty(page.getRecords())) {
      page.getRecords().add(out);
    }
    return page;
  }

  @Override
  public List<ResourceVehicleOut> listResourceVehicleOut(Map<String, Object> map) {
    return reportMapper.listResourceVehicleOut(map);
  }

  @Override
  public Page<ResourceVehicleOutDetail> pageResourceVehicleOutDetail(
      Page<ResourceVehicleOutDetail> page, Map<String, Object> map) {
    reportMapper.pageResourceVehicleOutDetail(page, map);
    ResourceVehicleOutDetail detail = new ResourceVehicleOutDetail();
    detail.setDisposalLandName("合计");
    BigDecimal netWeight = page.getRecords().stream().filter(l -> l.getNetWeight() != null)
        .map(ResourceVehicleOutDetail::getNetWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
    detail.setNetWeight(netWeight);
    if (CollUtil.isNotEmpty(page.getRecords())) {
      page.getRecords().add(detail);
    }
    return page;
  }

  @Override
  public List<ResourceVehicleOutDetail> listResourceVehicleOutDetail(Map<String, Object> map) {
    return reportMapper.listResourceVehicleOutDetail(map);
  }

  @Override
  public Page<ResourceUnsign> pageResourceUnsign(Page<ResourceUnsign> page,
      Map<String, Object> map) {
    // 超过12小时，且状态为进行中或待分配的预约单
    reportMapper.pageResourceUnsign(page, map);
    Date now = new Date();
    page.getRecords().forEach(l -> {
      if (l.getBeginTime() == null) {
        l.setOutStatus("未打卡");
        l.setInStatus("未打卡");
      } else {
        l.setOutStatus("已打卡");
        // 未打卡且出工地超过12小时
        int diff = DateUtils.differentHoursByMillisecond(l.getBeginTime(), now);
        Date endTime = l.getEndTime();
        if (endTime == null) {
          if (diff >= 12) {
            l.setInStatus("未打卡");
          } else {
            l.setInStatus("运输中");
          }
        } else {
          l.setInStatus("已打卡");
        }
      }
    });
    return page;
  }

  @Override
  public List<ResourceUnsign> listResourceUnsign(Map<String, Object> map) {
    List<ResourceUnsign> list = reportMapper.listResourceUnsign(map);
    Date now = new Date();
    list.forEach(l -> {
      if (l.getBeginTime() == null) {
        l.setOutStatus("未打卡");
        l.setInStatus("未打卡");
      } else {
        l.setOutStatus("已打卡");
        // 未打卡且出工地超过12小时
        int diff = DateUtils.differentHoursByMillisecond(l.getBeginTime(), now);
        Date endTime = l.getEndTime();
        if (endTime == null) {
          if (diff >= 12) {
            l.setInStatus("未打卡");
          } else {
            l.setInStatus("运输中");
          }
        } else {
          l.setInStatus("已打卡");
        }
      }
    });
    return list;
  }

  @Override
  public Page<ResourceVehicleOutTransport> pageResourceVehicleOutTransport(
      Page<ResourceVehicleOutTransport> page, Map<String, Object> map) {
    return reportMapper.pageResourceVehicleOutTransport(page, map);
  }

  @Override
  public List<ResourceVehicleOutTransport> listResourceVehicleOutTransport(
      Map<String, Object> map) {
    return reportMapper.listResourceVehicleOutTransport(map);
  }

  /**
   * 建筑垃圾进厂明细表->统计总净重
   */
  private Map<String, BigDecimal> listResourceVehicleTotalMap(Map<String, Object> map) {
    List<ResourceVehicleMonth> list = reportMapper.listResourceVehicleTotal(map);
    Map<String, BigDecimal> res = new HashMap<>();
    list.forEach(l -> res.put(l.getProjectId(), l.getTotalWeight()));
    return res;
  }

  /**
   * 建筑垃圾进厂月度汇总表->统计累计重量
   */
  private Map<String, BigDecimal> listResourceLandInfoTotalMap(Map<String, Object> map) {
    String beginDate = DateUtil.formatDate(DateUtil.beginOfYear(new Date()));
    map.put("beginDate", beginDate);
    List<ResourceLandInfo> list = reportMapper.listResourceLandInfoTotal(map);
    Map<String, BigDecimal> res = new HashMap<>();
    list.forEach(l -> res.put(
        l.getDisposalLandId() + "_" + l.getSysRubbishType() + "_" + l.getSysRubbishTypeSub(),
        l.getWeight()));
    return res;
  }
}
